# _*_coding:utf-8_*_
'''
Created on Feb 26, 2014
@author: jzhai
'''
from ATS.instrumentDriver.InstGen import CMTR
from ATS.instrumentDriver import InstConstant as const

OK = 0
debug_mode = False


class CMTR_E4980A(CMTR):
    def __init__(self, name, info_dict):
        super().__init__(name, info_dict)
        self.range_list = [0.1, 1, 10, 100, 300, 1000, 3000, 10000, 30000, 100000]
        print(name, info_dict)

    def __universalcom(self, cmdlist, func_id=0):
        """
        func_id: 0="write",1="read",2="ask",3="ask for values"
        """
        rval = None
        if not debug_mode:
            for cmd_str in cmdlist:
                if func_id == 0:
                    self.handler.write(cmd_str)
                elif func_id == 1:
                    rval = self.handler.read()
                elif func_id == 2:
                    rval = self.handler.ask(cmd_str)
                elif func_id == 3:
                    rval = self.handler.ask_for_values(cmd_str)
                elif func_id == 4:
                    rval = self.handler.read_values()
        else:
            for cmd in cmdlist:
                print("\n ", self.name, cmd)
                if func_id == 0:
                    self.handler.write(cmd)
                    if "?" not in cmd:
                        # clear errors
                        err = self.handler.ask(":syst:err?")
                        print("###error: ", err)
                elif func_id == 1:
                    rval = self.handler.read()
                elif func_id == 2:
                    rval = self.handler.ask(cmd)
                elif func_id == 3:
                    rval = self.handler.ask_for_values(cmd)
                elif func_id == 4:
                    rval = self.handler.read_values()
                print("\t", rval)
        return rval

    def findrange(self, value):
        irange = None
        if value in self.range_list:
            return value
        if value == 0:
            irange = 0
        elif value <= 0.1:
            irange = 0.1
        elif value > 1e5:
            irange = 1e5
        elif 0.1 < value <= 1:
            irange = 1
        elif 1 < value <= 10:
            irange = 10
        elif 10 < value <= 100:
            irange = 100
        elif 100 < value <= 300:
            irange = 300
        elif 300 < value <= 1000:
            irange = 1000
        elif 1000 < value <= 3000:
            irange = 3000
        elif 3000 < value <= 10000:
            irange = 10000
        elif 10000 < value <= 30000:
            irange = 30000
        elif 30000 < value <= 100000:
            irange = 100000
        return irange

    def reset(self):
        """
        Send reset cmd to C meter, and save the default setup in global inst_dict
        """
        cmd = ["*cls;*rst;SYST:KLOC 1"]
        self.__universalcom(cmd)
        setting = {"speed": const.CMTR_SPEED_NORMAL,
                   "mmodel": "CPD",
                   "filter": 1,
                   "trig_source": 0,
                   "display_page": "MEAS",
                   "klock": 1}
        self.clearinstsetting()
        self.setinstsetting(setting)
        return OK

    def setdisplaypage(self, page):
        """
        MEASurement|BNUMber|BCOunt|LIST|MSETup|CSETup|LTABle|LSETup|CA TAlog|
        SYSTem|SELF|MLARge|SCONfig|SERVice
        """
        setting = self.getinstsetting(["display_page"])
        if page == setting.get("display_page"):
            return OK
        else:
            cmd = [":DISP:PAGE %s" % page]
            self.setinstsetting({"display_page": page})
            self.__universalcom(cmd)
        return OK

    def klockenable(self, on_off):
        setting = self.getinstsetting(["klock"])
        if on_off == setting.get("klock", -1):
            return OK
        else:
            cmd = [":SYST:KLOC %d" % on_off]
            self.setinstsetting({"klock": on_off})
            self.__universalcom(cmd)
        return OK

    def setfrequency(self, frequency):
        setting = self.getinstsetting(["frequency"])
        if frequency == setting.get("frequency", 0):
            return OK
        else:
            cmd = [":FREQuency:CW %12.5e;:FREQuency:CW?" % frequency]
            rval = self.__universalcom(cmd, 3)
            self.setinstsetting({"frequency": rval[0]})
        return OK

    def setacdrive(self, acdrive):
        setting = self.getinstsetting(["acdrive"])
        if acdrive == setting.get("acdrive", -1):
            return OK
        else:
            cmd = [":VOLT %2.3f" % acdrive]
            self.setinstsetting({"acdrive": acdrive})
            self.__universalcom(cmd)
        return OK

    def setdcbias(self, dcbias):
        setting = self.getinstsetting(["dcbias"])
        if dcbias == setting.get("dcbias", -1):
            return OK
        else:
            cmd = [":BIAS:VOLT %f" % dcbias]
            self.setinstsetting({"dcbias": dcbias})
            self.__universalcom(cmd)
        return OK

    def outputenable(self, on_off):
        # print("output on_off",on_off)
        setting = self.getinstsetting(["onoff"])
        if on_off == setting.get("onoff", -1):
            return OK
        else:
            cmd = [":BIAS:state %d" % on_off]
            self.setinstsetting({"onoff": on_off})
            self.__universalcom(cmd)
        return OK

    def outputoff(self, mode):
        """
        mode: CMTR_OUTPUT_OFF=0#just turn off CMTR
                CMTR_OUTPUT_0V=1#set DC bias and AC drive to 0V, output still keep on, to avoid frequently switch the front panel indicator.
        """
        if mode == const.CMTR_OUTPUT_0V:
            self.setacdrive(0)
            self.setdcbias(0)
        else:  # CMTR_OUTPUT_0V default
            self.outputenable(0)
        return OK

    def setmeasmodel(self, mmodel):
        setting = self.getinstsetting(["mmodel"])
        if mmodel == setting.get("mmodel", ""):
            return OK
        else:
            cmd = [":FUNC:IMP %s" % mmodel]
            self.setinstsetting({"mmodel": mmodel})
            self.__universalcom(cmd)
        return OK

    def setmeasrange(self, irange):
        setting = self.getinstsetting(["irange"])
        irange_present = setting.get("irange", -1)
        irange = self.findrange(irange)
        if irange == irange_present:
            return OK
        else:
            if irange == 0:  # set auto
                cmd = [":FUNC:IMP:RANG:AUTO ON"]
            else:
                cmd = [":FUNC:IMP:RANG %s" % irange]
            self.setinstsetting({"irange": irange})
            self.__universalcom(cmd)
        return OK

    def setcompensation(self, compensation):
        """
        compensation = {"is_load":0/1,"is_open":0/1,"is_short":0/1,"cablelen":1.5, "method":0/1}
        """
        k_list = compensation.keys()
        if "cablelen" not in compensation:
            k_list.append("cablelen")
            compensation["cablelen"] = self.getcablelen()
        setting = self.getinstsetting(k_list)
        # cablelen = self.getcablelen()
        cmd_list = []
        for k in compensation:
            val = compensation[k]
            if val == setting.get(k, -1):
                continue
            if k == "is_open":
                cmd_list.append(":CORRection:OPEN:STATe %d" % val)
            elif k == "is_short":
                cmd_list.append(":CORRection:SHORT:STATe %d" % val)
            elif k == "is_load":
                cmd_list.append(":CORRection:LOAD:STATe %d" % val)
            elif k == "method":
                code = ["MULTiple", "SINGle"]
                cmd_list.append(":CORRection:method %s" % code[val])
            elif k == "cablelen":
                # cablelen = self.getcablelen()
                cmd_list.append(":CORRection:LENGth %d" % val)
                compensation["cablelen"] = val
        self.setinstsetting(compensation)
        self.__universalcom(cmd_list)
        return OK

    def setspeed(self, speed):
        code = ["SHORt", "MEDium", "LONG"]
        setting = self.getinstsetting(["speed"])
        if speed == setting.get("speed", -1):
            return OK
        else:
            cmd = ["APERture %s" % code[speed]]
            self.setinstsetting({"speed": speed})
            self.__universalcom(cmd)
        return OK

    def setautoinit(self, is_auto):
        setting = self.getinstsetting(["autoinit"])
        if is_auto == setting.get("autoinit", -1):
            return OK
        else:
            cmd = [":INIT:CONT %d" % is_auto]
            self.setinstsetting({"autoinit": is_auto})
            self.__universalcom(cmd)
        return OK

    def measure(self):
        # cmd = [":TRIG",":FETC?"]
        # cmd = [":TRIG;:FETC?"]
        # val = self.__universalcom(cmd, 3)
        # val = self.__universalcom([":TRIG"])
        val = self.__universalcom([":FETC?"], 3)
        return val
